-- the local upvalues bandwagon
local select = select
local UnitClass = UnitClass
local UnitIsDead = UnitIsDead
local UnitIsGhost = UnitIsGhost
local UnitIsPlayer = UnitIsPlayer
local UnitReaction = UnitReaction
local UnitIsConnected = UnitIsConnected
local UnitReactionColor = UnitReactionColor
local RAID_CLASS_COLORS = RAID_CLASS_COLORS
local UnitLevel = UnitLevel
local UnitIsTapped = UnitIsTapped
local UnitIstappedByPlayer = UnitIsTappedByPlayer
local UnitPowerType = UnitPowerType
local UnitClassification = UnitClassification
local UnitCreatureFamily = UnitCreatureFamily
local UnitCreatureType = UnitCreatureType
local UnitCanAttack = UnitCanAttack

local core = oUF.Jerry

local backdrop = core.backdrop
local statusbartexture = core.statusbartexture

-- colors
local powercolor = core.powercolor
local green = core.green
local white = core.white
local unknown = core.unknown

local auraIcon = core.auraIcon
local OnEnter, OnLeave = core.OnEnter, core.OnLeave
local getFontString = core.getFontString
local styleClicks = core.styleClicks
local styleCombatFeedback = core.styleCombatFeedback

local function updateLevel(self, event, unit)
	if self.unit ~= unit then return end

	local lvl = self.Lvl
	lvl:SetText(UnitLevel(unit))
	lvl:SetTextColor(1, 1, 1)
end

local function updateName(self, event, unit)
	if self.unit ~= unit then return end

	self.Name:SetText(UnitName(unit))
	updateLevel(self, event, unit)

	local cname, class = UnitClass(unit)
	self.Class:SetText(cname)
	local color = RAID_CLASS_COLORS[class] or white
	self.Class:SetVertexColor(color.r, color.g, color.b)
	self.Race:SetText(UnitRace(unit))
end

local function updateHealth(self, event, bar, unit, min, max)
	if UnitIsDead(unit) then
		bar:SetValue(0)
		bar.value:SetText("Dead")
	elseif UnitIsGhost(unit) then
		bar:SetValue(0)
		bar.value:SetText("Ghost")
	elseif not UnitIsConnected(unit) then
		bar:SetValue(0)
		bar.value:SetText("Offline")
	else
		local deficit = min - max
		if deficit == 0 then
			bar.value:SetFormattedText("%d/%d", min, max )
		else
			bar.value:SetFormattedText("%d/%d |cffff8080%d|r", min, max, deficit)
		end
	end

	local color = RAID_CLASS_COLORS[select(2, UnitClass(unit))] or unknown
	bar:SetStatusBarColor(color.r, color.g, color.b)
	bar.bg:SetTexture(color.r, color.g, color.b, .25)
end

local function updatePower(self, event, bar, unit, min, max)
	if max == 0 or UnitIsDead(unit) or UnitIsGhost(unit) or not UnitIsConnected(unit) then
		bar:SetValue(0)
		bar.value:SetText()
	else
		bar.value:SetFormattedText("%d/%d", min, max)
	end

	local color = powercolor(unit)
	bar:SetStatusBarColor(color.r, color.g, color.b)
	bar.bg:SetTexture(color.r, color.g, color.b, 0.25)
end

local function ShowMenu(self)
	local menu = self.menu
	if not menu then
		local unit = self.unit or self:GetAttribute("unit")
		menu = _G["PartyMemberFrame"..unit:sub(-1).."DropDown"]
		self.menu = menu
	end
	ToggleDropDownMenu(1, nil, menu, "cursor", 0, 0)
end

local function setStyle(settings, self, unit)
	styleClicks(self)
	self:SetAttribute("*type2", "showmenu")
	self.showmenu = ShowMenu
	-- Background
	self:SetBackdrop(backdrop)
	self:SetBackdropColor(0,0,0,1)

	-- Healthbar
	local hp = CreateFrame("StatusBar", nil, self)
	hp:SetHeight(22) -- 16 height if we're dealing with tiny or micro frames
	hp:SetStatusBarTexture(statusbartexture)
	hp:SetPoint("TOPLEFT")
	hp:SetPoint("TOPRIGHT")

	-- Healthbar background
	hp.bg = hp:CreateTexture(nil, "BORDER")
	hp.bg:SetAllPoints(hp)
	hp.bg:SetTexture(.25,.25,.25)

	-- Healthbar text
	hp.value = getFontString(hp)
	hp.value:SetPoint("RIGHT", -2, -1)

	self.Health = hp
	self.OverrideUpdateHealth = updateHealth

	local icon = hp:CreateTexture(nil, "OVERLAY")
	icon:SetHeight(16)
	icon:SetWidth(16)
	icon:SetPoint("TOP", self, 0, 8)
	icon:SetTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcons")
	self.RaidIcon = icon

	self.Name = getFontString(hp)
	self.Name:SetPoint("LEFT", 2, -1)
	self.UNIT_NAME_UPDATE = updateName

	-- Power Bar
	local pp = CreateFrame("StatusBar", nil, self)
	pp:SetHeight(16)
	pp:SetStatusBarTexture(statusbartexture)

	pp:SetPoint("LEFT")
	pp:SetPoint("RIGHT")
	pp:SetPoint("TOP", hp, "BOTTOM", 0, -1.35)

	local ppbg = pp:CreateTexture(nil, "BORDER")
	ppbg:SetAllPoints(pp)
	ppbg:SetTexture(.25,.25,.25)

	pp.bg = ppbg
	self.Power = pp
	self.OverrideUpdatePower = updatePower

	pp.value = getFontString(pp)
	pp.value:SetPoint("RIGHT", -2, 1)

	self.Lvl = getFontString(pp)
	self.Lvl:SetPoint("LEFT", pp, "LEFT", 2, 0)

	self.Class = getFontString(pp)
	self.Class:SetPoint("LEFT", self.Lvl, "RIGHT",  1, 0)

	self.Race = getFontString(pp)
	self.Race:SetPoint("LEFT", self.Class, "RIGHT",  1, 0)

	local leader = hp:CreateTexture(nil, "OVERLAY")
	leader:SetHeight(16)
	leader:SetWidth(16)
	leader:SetPoint("TOPLEFT", self, 0, 8)
	leader:SetTexture("Interface\\GroupFrame\\UI-Group-LeaderIcon")
	self.Leader = leader

	self.DebuffHighlightBackdrop = true -- oUF_DebuffHighlight Support, using the backdrop
	self.DebuffHighlightFilter = true -- only show debuffs I can cure

	styleCombatFeedback(self)

	local buffheight = 16 -- which happens to be the oUF default
	local buffwidth = settings["initial-width"]
	buffwidth = buffwidth - (buffwidth%16) -- make sure we have exactly enough room for the buffs

	-- no debuffs on my party frames
	local buffs = CreateFrame("Frame", nil, self)
	buffs.size = buffheight
	buffs:SetHeight(buffheight)
	buffs:SetWidth(buffwidth)
	buffs:SetPoint("TOPLEFT", self, "TOPRIGHT", 2, 0)
	buffs.initialAnchor = "TOPLEFT"
	buffs["growth-y"] = "DOWN"
	buffs.num = 40 -- floor(buffwidth/buffheight) -- one row of buffs
	-- buffs.filter = true
	self.Buffs = buffs

	self.Range = true
	self.inRangeAlpha = 1.0
	self.outsideRangeAlpha = 0.6

	self.PostCreateAuraIcon = auraIcon

	return self
end

local party	= oUF:Spawn("header", "oUF_Party", {
	["initial-width"] = 200,
	["initial-height"] = 39,
	setup = setStyle,
})
party:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 20, -150)
party:SetAttribute("yOffset", -31)
party:SetAttribute("showParty", true)
party:Show()
